# coding: utf-8
# Copyright (c) 2025 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import os
import unittest
import tempfile

from git.repo import Repo
from bmcgo.bmcgo_config import BmcgoConfig
from bmcgo.utils.tools import Tools
from bmcgo.functional.maintain import BmcgoCommand as MaintainCommand
from bmcgo.functional.conan_index_build import BmcgoCommand as BuildIndexCommand
from bmcgo.functional.fetch import BmcgoCommand as FetchCommand
from bmcgo.errors import BmcGoException

tools = Tools()


class TestMaintainCommand(unittest.TestCase):
    def __init__(self, methodName="TestMaintain"):
        super().__init__(methodName)
        self.test_package = "vpd/1.70.84"

    @classmethod
    def setUpClass(cls):
        cls.tmpdir = tempfile.TemporaryDirectory()
        os.chdir(cls.tmpdir.name)

        tools.run_command("conan profile new --detect default", ignore_error=True)
        tools.run_command("conan profile update env.CFLAGS=  default")
        tools.run_command("conan profile update env.CXXFLAGS=  default")

        Repo.clone_from(
            "https://gitcode.com/openUBMC/conan_index.git",
            to_path=cls.tmpdir.name,
            branch="main",
            depth=1,
        )
        return super().setUpClass()

    @classmethod
    def tearDownClass(cls):
        cls.tmpdir.cleanup()
        return super().tearDownClass()

    def setUp(self):
        self.cwd = os.getcwd()

    def tearDown(self):
        os.chdir(self.cwd)

    def test_base_on_commit(self):
        """
        基于commitid进行生成转维版本
        """
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            self.test_package,
            "-b",
            "main",
            "-c",
            "d0cb14b8de27e78628f8f897f5e9432b5177e9f4",
            "-v",
            "1.70.85",
        ]

        maintain = MaintainCommand(bconfig, args)
        maintain.run()

        args = ["-cp", "vpd/1.70.85", "-pr", "default", "--stage", "stable"]
        build = BuildIndexCommand(bconfig, args)
        build.run()

    def test_base_on_commit_build(self):
        """
        基于commitid进行生成带build后缀的转维版本
        """
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            self.test_package,
            "-b",
            "main",
            "-c",
            "d0cb14b8de27e78628f8f897f5e9432b5177e9f4",
            "-v",
            "1.70.85-build.1",
        ]

        maintain = MaintainCommand(bconfig, args)
        maintain.run()

        args = ["-cp", "vpd/1.70.85-build.1", "-pr", "default", "--stage", "stable"]
        build = BuildIndexCommand(bconfig, args)
        build.run()

    def test_base_on_multi_commit_build(self):
        """
        基于多个commitid进行生成带build后缀的转维版本
        """
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            self.test_package,
            "-b",
            "main",
            "-c",
            "d0cb14b8de27e78628f8f897f5e9432b5177e9f4",
            "-c",
            "47137ec99b4e663633cdf9a00ca552fb11d6090a",
            "-v",
            "1.70.87-build.1",
        ]

        maintain = MaintainCommand(bconfig, args)
        maintain.run()

        args = ["-cp", "vpd/1.70.87-build.1", "-pr", "default", "--stage", "stable"]
        build = BuildIndexCommand(bconfig, args)
        build.run()

    def test_patch_on_patch(self):
        """
        基于转维版本再次转维
        """
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            "vpd/1.70.85-build.1",
            "-b",
            "main",
            "-c",
            "e2b619d23739152cf334c5e55b76630edd51b470",
            "-v",
            "1.70.85-build.2",
        ]

        maintain = MaintainCommand(bconfig, args)
        maintain.run()

        args = ["-cp", "vpd/1.70.85-build.2", "-pr", "default", "--stage", "stable"]
        build = BuildIndexCommand(bconfig, args)
        build.run()

    def test_patch_with_wrong_commit(self):
        """
        基于错误的commitid进行生成转维版本异常场景
        """
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            self.test_package,
            "-b",
            "main",
            "-c",
            "e7cb14b8de27e78628f8f697f5e9432b5177e9f4",
            "-v",
            "1.70.87",
        ]

        with self.assertRaises(BmcGoException):
            maintain = MaintainCommand(bconfig, args)
            maintain.run()

    def test_build_patch_wrong_version(self):
        """
        转维版本号不满足要求场景
        """
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            self.test_package,
            "-b",
            "main",
            "-c",
            "d0cb14b8de27e78628f8f897f5e9432b5177e9f4",
        ]

        with self.assertRaises(BmcGoException):
            version = ["-v", "1.70.85-buildxx"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

        with self.assertRaises(BmcGoException):
            version = ["-v", "1.70.85-build.xx"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

        with self.assertRaises(BmcGoException):
            version = ["-v", "1.70.85-build1"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

        with self.assertRaises(BmcGoException):
            version = ["-v", "1.70.85.build.1"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

        with self.assertRaises(BmcGoException):
            version = ["-v", "01.70.85-build.1"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

        with self.assertRaises(BmcGoException):
            version = ["-v", "1.70.8a-build.1"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

        with self.assertRaises(BmcGoException):
            version = ["-v", "1.70.8-x.1"]
            maintain = MaintainCommand(bconfig, args + version)
            maintain.run()

    def test_patch_with_add_file(self):
        """
        新增文件场景
        """
        cwd = os.getcwd()
        tmpdir = tempfile.TemporaryDirectory()
        bconfig = BmcgoConfig()
        args = ["-pi", f"{self.test_package}@{tools.conan_user}/stable", "-p", tmpdir.name]
        fetch_cmd = FetchCommand(bconfig, args)
        fetch_cmd.run()
        vpd_path = os.path.join(tmpdir.name, "vpd")
        os.chdir(vpd_path)
        cmd = "cp README.md readme.md"
        tools.run_command(cmd)
        cmd = "git add -A"
        tools.run_command(cmd)
        cmd = "git commit -m 'test add readme.md'"
        tools.run_command(cmd)
        cmd = "git format-patch -1 HEAD --numbered-files"
        tools.run_command(cmd)
        cmd = "mv 1 test_file_add.patch"
        tools.run_command(cmd)
        patch_file = os.path.join(vpd_path, "test_file_add.patch")
        os.chdir(cwd)
        self._patch_vpd_with_file(patch_file, "1.70.84-build.10")

    def test_patch_with_rename_file(self):
        """
        新增文件场景
        """
        cwd = os.getcwd()
        tmpdir = tempfile.TemporaryDirectory()
        bconfig = BmcgoConfig()
        args = ["-pi", f"{self.test_package}@{tools.conan_user}/stable", "-p", tmpdir.name]
        fetch_cmd = FetchCommand(bconfig, args)
        fetch_cmd.run()
        vpd_path = os.path.join(tmpdir.name, "vpd")
        os.chdir(vpd_path)
        cmd = "mv README.md readme.md"
        tools.run_command(cmd)
        cmd = "git add -A"
        tools.run_command(cmd)
        cmd = "git commit -m 'test rename readme.md'"
        tools.run_command(cmd)
        cmd = "git format-patch -1 HEAD --numbered-files"
        tools.run_command(cmd)
        cmd = "mv 1 test_file_rename.patch"
        tools.run_command(cmd)
        patch_file = os.path.join(vpd_path, "test_file_rename.patch")
        os.chdir(cwd)
        self._patch_vpd_with_file(patch_file, "1.70.84-build.12")

    def test_patch_with_rename_file(self):
        """
        新增文件场景
        """
        cwd = os.getcwd()
        tmpdir = tempfile.TemporaryDirectory()
        bconfig = BmcgoConfig()
        args = ["-pi", f"{self.test_package}@{tools.conan_user}/stable", "-p", tmpdir.name]
        fetch_cmd = FetchCommand(bconfig, args)
        fetch_cmd.run()
        vpd_path = os.path.join(tmpdir.name, "vpd")
        os.chdir(vpd_path)
        cmd = "rm README.md"
        tools.run_command(cmd)
        cmd = "git add -A"
        tools.run_command(cmd)
        cmd = "git commit -m 'test remove readme.md'"
        tools.run_command(cmd)
        cmd = "git format-patch -1 HEAD --numbered-files"
        tools.run_command(cmd)
        cmd = "mv 1 test_file_remove.patch"
        tools.run_command(cmd)
        patch_file = os.path.join(vpd_path, "test_file_remove.patch")
        os.chdir(cwd)
        self._patch_vpd_with_file(patch_file, "1.70.84-build.13")

    def _patch_vpd_with_file(self, patch_file, patch_version):
        bconfig = BmcgoConfig()
        args = [
            "-cp",
            self.test_package,
            "-b",
            "main",
            "-p",
            patch_file,
            "-v",
            patch_version,
        ]

        maintain = MaintainCommand(bconfig, args)
        maintain.run()

        args = ["-cp", f"vpd/{patch_version}", "-pr", "default", "--stage", "stable"]
        build = BuildIndexCommand(bconfig, args)
        build.run()

